import numpy as np
import pandas as pd
from datetime import datetime,timedelta
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.linear_model import LogisticRegression
import warnings
warnings.filterwarnings('ignore')

# 生成各种有效信息
def create_data():
    header = ['姓名','成为积极分子日期','思想汇报质量得分','培训成绩','是否成为积极分子']
    # 随便生成一些测试姓名,不重复
    ls = ['a','b','c','d','e','f','g','h','i']
    name = []
    for i in ls:
        for j in ls:
            for k in ls:
                name.append(str(i)+str(j)+str(k))
    name = list(set(name))
    data_number = len(name)

    # 生成日期
    now_time = datetime.now()
    delta_time_ls = [np.random.randint(50,300) for i in range(data_number)]
    each_time = [now_time - timedelta(days=i) for i in delta_time_ls]

    # 生成思想汇报质量得分、培训成绩
    score_think = [np.random.randint(20,100) for i in range(data_number)]
    score_train = [np.random.randint(20,100) for i in range(data_number)]

    # 生成每个人是否已成为预备党员，以此为目标变量
    ready = []
    # 根据成绩情况构造一下,与3个因素应该都有关系
    for t, i, j in zip(delta_time_ls, score_think, score_train):
        if i + j >= 140 and t >= 180:
            goal = 1
        else:
            goal = 0
        ready.append(goal)

    # 将所有信息合成表
    df = pd.DataFrame(np.c_[np.array(name),np.array(each_time),np.array(score_think),np.array(score_train),np.array(ready)])
    df.columns = header
    return df

class MachineLearn:
    def __init__(self,df):
        x = df.iloc[:,1:4]
        y = df.iloc[:,-1:].astype('int')
        x.iloc[:,0] = pd.DataFrame(np.array([(datetime.now()-i).days for i in x.iloc[:,0]]))
        # 为将缩放规则应用到新数据将均值、标准差进行计算
        self.avg1 = x.iloc[:,:1].mean()[0]
        self.avg2 = x.iloc[:,1:2].mean()[0]
        self.avg3 = x.iloc[:,2:].mean()[0]
        self.std1 = x.iloc[:, :1].std()[0]
        self.std2 = x.iloc[:, 1:2].std()[0]
        self.std3 = x.iloc[:, 2:].std()[0]
        x = StandardScaler().fit_transform(x)  # 数据标准化
        self.x_train, self.x_test, self.y_train, self.y_test = train_test_split(x, y, random_state=666, test_size=0.3)
    # 网格搜索交叉验证
    def grid(self):
        lr = LogisticRegression()
        model = GridSearchCV(lr, param_grid={'C': range(1,100)})
        model.fit(self.x_train, self.y_train)
        score = model.score(self.x_test, self.y_test)
        return score, model
    # 逻辑回归
    def logic(self):
        model = LogisticRegression(solver="sag",C=1.5,fit_intercept=True,max_iter=500,multi_class='multinomial')
        model.fit(self.x_train,self.y_train)
        score = model.score(self.x_test,self.y_test)
        return score, model

def choose_model():
    df = create_data()
    ml = MachineLearn(df)
    df = pd.DataFrame(np.array([[ml.avg1,ml.avg2,ml.avg3],[ml.std1,ml.std2,ml.std3]]))
    df.columns = ['时长','思想分数','培训成绩']
    df.index = ['均值','标准差']
    score1, model1 = ml.grid()
    score2, model2 = ml.logic()
    if score1 >= score2:
        model = model1
    else:
        model = model2
    return model, df

class Judge:
    def __init__(self,name,date,score1,score2):
        self.name = name
        self.date = date
        self.score1 = score1
        self.score2 = score2

    def consider(self):
        model, df = choose_model()
        date = (datetime.now()-self.date).days
        date = (date-df['时长'].均值)/df['时长'].标准差
        score1 = (self.score1-df['思想分数'].均值)/df['思想分数'].标准差
        score2 = (self.score2-df['培训成绩'].均值)/df['培训成绩'].标准差
        x = np.array([[date, score1, score2]])
        y_or_n = model.predict(x)
        return y_or_n[0]

    def input_output(self):
        ls = []
        for i in range(5):
            ls.append(self.consider())
        s = '是' if ls.count(1) > 2 else '不是'
        return f'{self.name}{s}预备党员'

if __name__ == '__main__':
    # 输入输出参数用例(姓名,成为积极分子的日期,思想汇报质量得分,培训成绩）
    judge1 = Judge('甲', datetime.now() - timedelta(days=200), 90, 70)
    result1 = judge1.input_output()
    judge2 = Judge('乙', datetime.now() - timedelta(days=250), 90, 60)
    result2 = judge2.input_output()
    judge3 = Judge('丙', datetime.now() - timedelta(days=200), 50, 60)
    result3 = judge3.input_output()
    judge4 = Judge('丁', datetime.now() - timedelta(days=300), 60, 60)
    result4 = judge4.input_output()
    print(result1, result2, result3, result4)
